

// #include <iostream>
// #include <string>
// #include <vector>
// #include <unistd.h>
// #include <pthread.h>

// int tickets = 10000;

// class ThreadData
// {
// public:
//     ThreadData(const std::string &threadname, pthread_mutex_t *mutex_p)
//         : threadname_(threadname),
//           mutex_p_(mutex_p)
//     {
//     }
//     ~ThreadData()
//     {
//     }

// public:
//     std::string threadname_;
//     pthread_mutex_t *mutex_p_;
// };

// void *getTicket(void *args)
// {
//     ThreadData *td = static_cast<ThreadData *>(args);
//     while (true)
//     {
//         // 加锁
//         pthread_mutex_lock(td->mutex_p_);
//         if (tickets > 0)
//         {
//             usleep(1254);
//             std::cout << td->threadname_ << " 正在进行抢票: " << tickets << std::endl;
//             // 用这段时间来模拟真实的抢票要花费的时间
//             tickets--;
//             // 解锁
//             pthread_mutex_unlock(td->mutex_p_);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->mutex_p_);
//             break;
//         }
//         // 当抢完票就完了吗？当然不是，要做其他事情。
//         usleep(1000); // 模拟形成一个订单给用户
//     }
//     return nullptr;
// }

// int main()
// {
// #define NUM 4
//     pthread_mutex_t lock;
//     pthread_mutex_init(&lock, nullptr);
//     std::vector<pthread_t> tids(NUM);
//     for (int i = 0; i < NUM; i++)
//     {
//         char buffer[64];
//         snprintf(buffer, sizeof(buffer), "thread: %d", i + 1);
//         ThreadData *td = new ThreadData(buffer, &lock);
//         pthread_create(&tids[i], nullptr, getTicket, td);
//     }
//     for (const auto &tid : tids)
//     {
//         pthread_join(tid, nullptr);
//     }
//     pthread_mutex_destroy(&lock);
//     return 0;
// }

#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include "Mutex.hpp"

int tickets = 10000;

// 全局的锁使用PTHREAD_ MUTEX_ INITIALIZER初始化，不需要再销毁
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

class ThreadData
{
public:
    ThreadData(const std::string &threadname, pthread_mutex_t *mutex_p)
        : threadname_(threadname),
          mutex_p_(mutex_p)
    {
    }
    ~ThreadData()
    {
    }

public:
    std::string threadname_;
    pthread_mutex_t *mutex_p_;
};

void *getTicket(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);
    while (true)
    {
        {
            // RAII风格的加锁
            LockGuard lockguard(&lock); // 局部变量的生命周期是代码块，在下次while循环之前，会被析构，重新定义。
            // 加锁
            // pthread_mutex_lock(td->mutex_p_);
            if (tickets > 0)
            {
                usleep(1254);
                std::cout << td->threadname_ << " 正在进行抢票: " << tickets << std::endl;
                // 用这段时间来模拟真实的抢票要花费的时间
                tickets--;
                // 解锁
                // pthread_mutex_unlock(td->mutex_p_);
            }
            else
            {
                // pthread_mutex_unlock(td->mutex_p_);
                break;
            }
            // 当抢完票就完了吗？当然不是，要做其他事情。
            usleep(1000); // 模拟形成一个订单给用户
        }
    }
    return nullptr;
}

int main()
{
#define NUM 4

    // 静态的锁使用PTHREAD_ MUTEX_ INITIALIZER初始化，不需要再销毁
    // static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;

    std::vector<pthread_t> tids(NUM);
    for (int i = 0; i < NUM; i++)
    {
        char buffer[64];
        snprintf(buffer, sizeof(buffer), "thread: %d", i + 1);
        ThreadData *td = new ThreadData(buffer, &lock);
        pthread_create(&tids[i], nullptr, getTicket, td);
    }
    for (const auto &tid : tids)
    {
        pthread_join(tid, nullptr);
    }
    return 0;
}

// #include <iostream>
// #include <string>
// #include <unistd.h>
// #include <pthread.h>

// int tickets = 10000;

// void *getTicket(void *args)
// {
//     std::string username = static_cast<const char *>(args);
//     while (true)
//     {

//         if (tickets > 0)
//         {
//             usleep(1254); // 1秒 = 1000毫秒 = 1000 000 微妙 = 10^9纳秒
//             // 值得抢
//             std::cout << username << " 正在进行抢票: " << tickets << std::endl;
//             // 用这段时间来模拟真实的抢票要花费的时间
//             tickets--;
//         }
//         else
//         {
//             break;
//         }
//     }

//     // other code

//     return nullptr;
// }

// int main()
// {

//     pthread_t t1, t2, t3, t4;
//     pthread_create(&t1, nullptr, getTicket, (void *)"thread 1");
//     pthread_create(&t2, nullptr, getTicket, (void *)"thread 2");
//     pthread_create(&t3, nullptr, getTicket, (void *)"thread 3");
//     pthread_create(&t4, nullptr, getTicket, (void *)"thread 4");

//     pthread_join(t1, nullptr);
//     pthread_join(t2, nullptr);
//     pthread_join(t3, nullptr);
//     pthread_join(t4, nullptr);
//     return 0;
// }